#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <memory>
#include <unordered_map>

static const std::string line_sep = "\r\n";
static const std::string head_sep = ": ";
static const std::string status_sep = " ";
static const std::string wwwroot = "wwwroot";
static const std::string homepage = "index.html";
static const std::string httpversion = "HTTP/1.0";

class HttpRequest
{
private:
    std::string GetOneLine(std::string &req)
    {
        if (req.empty())
            return req;

        auto pos = req.find(line_sep);
        if (pos == std::string::npos)
            return std::string();
        std::string temp = req.substr(0, pos);
        req.erase(0, pos + line_sep.size());
        if (temp.empty())
            return line_sep; // 读到 "\r\n"

        return temp;
    }

    void HandlerReqLine()
    {
        std::stringstream ss(_req_line);
        ss >> _method >> _url >> _version;

        _path += _url;
        if (_path[_path.size() - 1] == '/')
        {
            _path += homepage;
        }
    }

    bool HeadHelper(std::string &head, std::string *k, std::string *v)
    {
        auto pos = head.find(head_sep);
        if (pos == std::string::npos)
            return false; // 检查空指针

        *k = head.substr(0, pos);
        *v = head.substr(pos + head_sep.size());
        return true;
    }

    void HandlerReqHead()
    {
        for (auto head : _req_head)
        {
            std::string k, v;

            if (HeadHelper(head, &k, &v))
                _heads[k] = v;
        }
    }

public:
    HttpRequest() : _blank(line_sep), _path(wwwroot)
    {
    }

    void Unserialize(std::string req)
    {
        _req_line = GetOneLine(req);
        if (_req_line.empty())
            return;

        while (!req.empty())
        {
            std::string temp = GetOneLine(req);
            if (temp.empty())
                break;
            if (temp == line_sep)
            {
                _req_data = req;
                break;
            }
            _req_head.push_back(temp);
        }

        HandlerReqLine();
        HandlerReqHead();
    }

    void Print()
    {
        // std::cout << _req_line << std::endl;
        // for (auto head : _req_head)
        // {
        //     std::cout << head << std::endl;
        // }
        // std::cout << _req_data << std::endl;

        // std::cout << "----------------------------" << std::endl << std::endl;
        // std::cout << "method" << ": " << _method << std::endl;
        // std::cout << "url" << ": " << _url << std::endl;
        // std::cout << "version" << ": " << _version << std::endl;
        // for (auto head : _heads)
        // {
        //     std::cout << head.first << ": " << head.second << std::endl;
        // }

        std::cout << std::endl;
        std::cout << "------------------------" << std::endl;
        std::cout << "req_data : " << _req_data << std::endl;
        std::cout << "------------------------" << std::endl;
    }

    std::string method()
    {
        return _method;
    }

    std::string Path()
    {
        return _path;
    }

    std::unordered_map<std::string, std::string> Head()
    {
        return _heads;
    }

    std::string ReqData()
    {
        return _req_data;
    }

    ~HttpRequest()
    {
    }

private:
    // 原始协议内容
    std::string _req_line;
    std::vector<std::string> _req_head;
    std::string _blank;
    std::string _req_data; // 存储 POST 请求的请求体

    // 期望解析到的结果
    std::string _path;
    std::string _method;
    std::string _url;
    std::string _version;

    std::unordered_map<std::string, std::string> _heads;
};

// 需要将结构化的数据拼接成 序列化字符串
class HttpResponse
{
public:
    HttpResponse() : _resp_blank(line_sep), _http_version(httpversion)
    {
    }

    std::string Serialize()
    {
        _status_line = _http_version + status_sep + std::to_string(_status_code) + status_sep + _status_desc + line_sep;

        for (auto head : _heads)
        {
            std::string temp = head.first + head_sep + head.second + line_sep;
            _resp_head.emplace_back(temp);
        }
        // 序列化
        std::string respstr = _status_line;
        for (auto head : _resp_head)
        {
            respstr += head;
        }
        respstr += _resp_blank;
        respstr += _resp_data;

        return respstr;
    }

    void AddRespHead(std::string k, std::string v)
    {
        _heads[k] = v;
    }

    void AddStatusLine(int code, const std::string &desc)
    {
        _status_code = code;
        _status_desc = desc;
    }

    void AddRespData(const std::string &content)
    {
        _resp_data = content;
    }

    // std::unordered_map<std::string, std::string>& Heads()
    // {
    //     return _heads;
    // }

    ~HttpResponse()
    {
    }

private:
    // 构建应答的必要字段
    std::string _http_version;
    int _status_code;
    std::string _status_desc;
    std::unordered_map<std::string, std::string> _heads;

    // 应答的结构化字段
    std::string _status_line;
    std::vector<std::string> _resp_head;
    std::string _resp_blank;
    std::string _resp_data;
};

class Factory
{
public:
    static std::shared_ptr<HttpRequest> BuildHttpRequest()
    {
        return std::make_shared<HttpRequest>();
        // return std::shared_ptr<HttpRequest>(); // 这不是在栈上创建对象？？
    }

    static std::shared_ptr<HttpResponse> BuildHttpResponse()
    {
        return std::make_shared<HttpResponse>();
        // return std::shared_ptr<HttpResponse>();
    }
};

class HttpServer
{
public:
    HttpServer()
    {
    }

    std::string ReadFileContent(std::string path, int *size)
    {
        std::ifstream in(path.c_str(), std::ifstream::binary);
        if (!in.is_open())
            return std::string();

        in.seekg(0, in.end);
        int filesize = in.tellg();

        in.seekg(0, in.beg);

        std::string content;

        content.resize(filesize);

        in.read((char *)content.c_str(), filesize);
        in.close();

        *size = filesize;
        return content;
    }
    // #define TEST 1

    std::string HttpServerHandler(std::string reqstr)
    {
#ifdef TEST
        std::cout << reqstr;

#else
        std::cout << reqstr;
        std::cout << std::endl <<"-----------------------------------------" << std::endl;

        // 收到请求
        std::shared_ptr<HttpRequest> request = Factory::BuildHttpRequest();
        request->Unserialize(reqstr);

        int contentsize = 0;
        std::string text = ReadFileContent(request->Path(), &contentsize);

        // 做出应答
        std::shared_ptr<HttpResponse> response = Factory::BuildHttpResponse();

        // 处理 POST 请求
        if (request->method() == "POST" || request->method() == "post")
        {
            int content_length = 0;
            auto it = request->Head().find("Content-Length");
            if (it != request->Head().end())
            {
                content_length = std::stoi(request->Head()["Content-Length"]);
            }

            if (content_length > 0 && content_length == request->ReqData().size())
            {
                std::string resp_data = request->ReqData(); // 获取 POST 请求体

                // 返回成功响应
                response->AddStatusLine(200, "OK");
                response->AddRespHead("Content-Length", std::to_string(resp_data.size()));
                response->AddRespHead("Content-Type", "text/html");
                response->AddRespData(resp_data);
            }
            else
            {
                // 返回错误相应
                response->AddStatusLine(400, "Bad Request");
                response->AddRespHead("Content-Length", "0");
                response->AddRespHead("Content-Type", "text/html");
            }
        }
        else // 非 POST 请求 -- GET 请求
        {
            response->AddStatusLine(200, "OK");
            response->AddRespHead("Content-Length", std::to_string(contentsize));
            response->AddRespHead("Content-Type", "text/html");
            response->AddRespData(text);

        }

        std::string ret = response->Serialize();
        return ret;
#endif
    }

    ~HttpServer()
    {
    }

private:
};